iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 22
1

前言

因為 UserDefaults 的瑕疵?!我又找了別的方法存值。
那個方法就是放進 App 安裝完成後的沙盒 (sandbox)

沙盒簡介

App 安裝完成後,iOS 會為每個 App 建立專屬的沙盒,裡面就包含三個區域:

1. 專案檔案區 (bundle container)

裡面存放 App 的執行檔及事先放進 XCode 專案中的檔案(常見的是圖檔或資料庫)。
這裡的資料是惟讀的!若想要儲存資料,要放到資料儲存區或 iCloud 區

2. 資料儲存區 (data container)

在這區裡面,iOS又會建立三個重要的資料夾

  • Documents:存放使用者建立的資料(檔案)
  • Library:底下又分兩個子目錄
    • Application Support:存放 App 所需要的範本檔或特定的資源檔。
    • Caches:暫存區域。當裝置的儲存空間不足時,iOS 會主動刪除這個目錄下的檔案。
  • tmp:暫存區域。存在這的資料,只能仰賴程式設計者刪除。

以上四個目錄在 iTunes 備份時,只有 Documents 和 Library/Application Support 內的資料會備份。

Apple在上架審核時會對那兩個目錄下的資料是否有備份價值特別要求。如果沒有備份價值,又沒設定成「不需要備份」,上架審核就會不通過。

細節請參考官方說明:

iOS Data Storage Guidelines

可以透過以下兩個函數取得 data container 的進入點(路徑)

  • NSHomeDirectory(): 回傳 data container 所在的根目錄,結尾不包含「/」符號。
  • NSTemporaryDirectory(): 回傳 tmp 目錄,結尾包含「/」符號。

具有存擋的資料類別有 String、Data、NSArray、NSDictionary 與 UserDefaults

其中 NSSet 類別是不具備存檔功能的
另外,路徑格式需為 URL 格式,相關參考如下

URL:統一資源定位符

3. iCloud 區

所有放到這個區域底下的資料,系統都會自動把它同步到雲端。

目錄與檔案的操作

以下操作都是 FileManager.default 底下的方法

1.建立 (目錄與檔案的方法不同)

目錄

.creatdDirectory(atPath: 路徑, withIntermediateDirectories: true, attributes: nil)

withIntermediateDirectories: true 表示若路徑不存在的時候會自動建立目錄(含上層目錄也會一併創建)

檔案

.creatFile(atPath: 路徑, contents: data, atrributes: nil)

創建檔案的同時會順便寫入 data 的資料
EX: data = "hello".data(using: .utf8)

2.複製 (目錄與檔案的方法相同)

.copyItem(atPath: 路徑1, toPath: 路徑2)

3.移動或更改名稱 (目錄與檔案的方法相同)

.moveItem(atPath: 路徑1, toPath:路徑2)

4.刪除 (目錄與檔案的方法相同)

.removeItem(atPath: 路徑)

5.檢查是否存在 (目錄與檔案的方法相同)

.fileExists(atPath: 路徑)

設定檔案不要備份

先建立 test.txt 檔案,在設定其為「不用備份」

    override func viewDidLoad() {
        super.viewDidLoad()
        let fileManager = FileManager.default
        let fileName = NSHomeDirectory() + "/Documents/test.txt"
        
        //建立 test.txt 檔案
        fileManager.createFile(atPath: fileName, contents: nil, attributes: nil)
        //將檔案路徑轉換成 URL 格式
        var url = URL(fileURLWithPath: fileName)
        do {
            var noBackUp = URLResourceValues()
            noBackUp.isExcludedFromBackup = true
            try url.setResourceValues(noBackUp)
        } catch {
            print("noBackUp setting fail")
        }
    }

一般型態的檔案存取

override func viewDidLoad() {
        super.viewDidLoad()
        
        //文字檔案讀取
        var fileName = NSHomeDirectory() + "/Documents/test.txt"
        //let url = URL(fileURLWithPath: fileName)
        
        do {
            try "hello".write(toFile: fileName, atomically: true, encoding: .utf8)
        } catch {
            print("save file fail")
        }
        
        do {
            let sayHello = try String(contentsOfFile: fileName, encoding: .utf8)
            print(sayHello) //印出 hello
        } catch {
            print("read file fail")
        }
        
        //二進位檔案讀取
        var image = UIImage(named: "test.jpg")
        // 設定圖片的存檔檔名
        fileName = NSHomeDirectory() + "/Documents/image.dat"
        let url = URL(fileURLWithPath: fileName)
        
        // 存檔
        let data = UIImagePNGRepresentation(image!)
        do {
            try data?.write(to: url)
        } catch {
            print("save image file fail")
        }
        
        //從檔案取出圖片
        if let data = try? Data(contentsOf: url) {
            image = UIImage(data: data)
        } else {
            print("read image file fail")
        }
    }

上一篇
Day21 - 消失的 Tab Bar
下一篇
Day23 - 建立 *.txt 檔案存取資料
系列文
無中生有-從SWIFT語法學習到iOS APP的開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言